package com.csw.android.ffmpegtest.ui.section3

import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.Surface
import android.view.View
import androidx.camera.core.*
import androidx.camera.extensions.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import com.csw.android.dev_utils.ex.CloseableEx.closeIgnoreException
import com.csw.android.dev_utils.ex.FileEx.deepDelete
import com.csw.android.dev_utils.ex.FileEx.recreate
import com.csw.android.dev_utils.handler.MainHandler
import com.csw.android.dev_utils.ui.BaseActivity
import com.csw.android.dev_utils.utils.ToastUtils
import com.csw.android.ffmpegtest.R
import com.csw.android.ffmpegtest.app.Config
import com.csw.android.ffmpegtest.databinding.LayoutSection301Binding
import com.csw.android.ffmpegtest.ui.base.DataBindingFragment
import com.csw.android.ffmpegtest.view.ClickOrLongPressView
import com.tbruyelle.rxpermissions3.RxPermissions
import java.io.File
import java.io.FileOutputStream
import java.util.concurrent.Executors

/**
 * 在 Android 平台使用 Camera API 进行视频的采集，分别使用 SurfaceView、TextureView 来预览 Camera 数据，
 * 取到 NV21 的数据回调。
 *
 * 这里使用CameraX，最后发现，cameraX虽然使用起来简单，但最后获取到的图像是压缩后的jpg图像，并不是yuv，还是要
 * 直接用camera api才能达到锻炼目的
 * https://blog.csdn.net/sihaiyinan/article/details/102487935
 *
 * cameraX 的VideoCapture很多API只能在cameraX包下的类访问，可能是还属于测试功能，所以代码会报红，但编译运行
 * 不会有问题，大概吧。。。
 */
@SuppressLint("RestrictedApi")
class Section301 : DataBindingFragment<LayoutSection301Binding>() {

    override fun getContentViewID(): Int {
        return R.layout.layout_section_301
    }

    override fun initView(rootView: View, savedInstanceState: Bundle?) {
        super.initView(rootView, savedInstanceState)
        dataBinding?.root?.visibility = View.GONE
//        dataBinding?.previewView?.implementationMode =
//            PreviewView.ImplementationMode.PERFORMANCE//SurfaceView
        dataBinding?.previewView?.implementationMode =
            PreviewView.ImplementationMode.COMPATIBLE//TextureView
        activity?.run {
            if (this is BaseActivity) {
                setFullScreen(true)
            }
        }
    }

    override fun initListener() {
        super.initListener()
        dataBinding?.clickOrLongPressView?.run {
            setOnClickListener {
                imageCapture?.takePicture(
                    Executors.newSingleThreadExecutor(),
                    object : ImageCapture.OnImageCapturedCallback() {
                        override fun onCaptureSuccess(image: ImageProxy) {
                            super.onCaptureSuccess(image)
                            //图片里面的数据即是jpg数据
                            val planes = image.planes
                            if (planes.isNotEmpty()) {
                                val byteBuffer = planes[0].buffer
                                val buffer = ByteArray(byteBuffer.capacity())
                                byteBuffer.get(buffer)
                                savePicture(buffer)
                            }
                        }

                        override fun onError(exception: ImageCaptureException) {
                            super.onError(exception)
                            ToastUtils.showShort("无法获取截图")
                        }
                    })
            }
            onLongPressListener = object : ClickOrLongPressView.OnLongPressListener {
                override fun onStartPress() {
                    activity?.run {
                        if (ActivityCompat.checkSelfPermission(
                                this,
                                Manifest.permission.RECORD_AUDIO
                            ) == PackageManager.PERMISSION_GRANTED
                        ) {
                            val filePath = Config.Section301.getVideoPath()
                            val file = File(filePath)
                            file.deepDelete()
                            file.createNewFile()
                            videoCapture?.startRecording(
                                VideoCapture.OutputFileOptions.Builder(file).build(),
                                Executors.newSingleThreadExecutor(),
                                object : VideoCapture.OnVideoSavedCallback {
                                    override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
                                        mainHandler.post {
                                            ToastUtils.showShort("视频录制成功：${file.path}")
                                        }
                                    }

                                    override fun onError(
                                        videoCaptureError: Int,
                                        message: String,
                                        cause: Throwable?
                                    ) {
                                        mainHandler.post {
                                            ToastUtils.showShort("视频录制失败：${file.path}")
                                        }
                                    }
                                }
                            )
                        }
                    }
                }

                override fun onEndPress() {
                    videoCapture?.stopRecording()
                }
            }
        }
    }

    private val mainHandler = MainHandler()

    private fun savePicture(buffer: ByteArray) {
        Thread {
            val filePath = Config.Section301.getPicturePath()
            val file = File(filePath)
            file.recreate()
            var fos: FileOutputStream? = null
            try {
                fos = FileOutputStream(file)
                fos.write(buffer)
                fos.flush()
                mainHandler.post {
                    ToastUtils.showShort("照片保存成功：${file.path}")
                }
            } catch (e: Exception) {
                e.printStackTrace()
                mainHandler.post {
                    ToastUtils.showShort("照片保存失败：${file.path}")
                }
            } finally {
                fos.closeIgnoreException()
            }
        }.start()
    }

    override fun initData() {
        super.initData()
        RxPermissions(this).request(
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
        ).subscribe {
            if (it) {
                dataBinding?.root?.visibility = View.VISIBLE
                initCamera()
            } else {
                activity?.finish()
            }
        }
    }

    private val cameraSelector = CameraSelector.Builder()
        .requireLensFacing(CameraSelector.LENS_FACING_FRONT)//请求后置摄像头LENS_FACING_BACK
        .build()

    //预览
    private val previewBuilder = Preview.Builder()
        .setTargetAspectRatio(AspectRatio.RATIO_16_9)//宽高比
//        .setTargetResolution(Size(1080, 1920))//分辨率
        .setTargetRotation(Surface.ROTATION_0)//旋转


    //拍照
    private val imageCaptureBuilder = ImageCapture.Builder()
        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)//设置模式，高质量|低延迟
        .setTargetAspectRatio(AspectRatio.RATIO_16_9)//宽高比
//        .setTargetResolution(Size(1080, 1920))//分辨率
        .setTargetRotation(Surface.ROTATION_0)//旋转


    //录像
    private val videoCaptureBuilder = VideoCapture.Builder()
    var preview: Preview? = null
    var imageCapture: ImageCapture? = null
    var videoCapture: VideoCapture? = null
    private fun initCamera() {
        activity?.run {
            setPreview(previewBuilder, cameraSelector)
            setImageCapture(imageCaptureBuilder, cameraSelector)


            val preview = previewBuilder.build()
            val imageCapture = imageCaptureBuilder.build()
            val videoCapture = videoCaptureBuilder.build()
            this@Section301.preview = preview
            this@Section301.imageCapture = imageCapture
            this@Section301.videoCapture = videoCapture
            val processCameraProvider = ProcessCameraProvider.getInstance(this).get()
            processCameraProvider.unbindAll()
            processCameraProvider.bindToLifecycle(
                this@Section301,
                cameraSelector,
                preview,
                imageCapture,
                videoCapture,
            )
            dataBinding?.previewView?.run {
                preview.setSurfaceProvider(surfaceProvider)
            }
        }
    }

    private fun setPreview(previewBuilder: Preview.Builder, cameraSelector: CameraSelector) {
        //自动效果，可能是白平衡那些
        val autoPreviewExtender = AutoPreviewExtender.create(previewBuilder)
        if (autoPreviewExtender.isExtensionAvailable(cameraSelector)) {
            autoPreviewExtender.enableExtension(cameraSelector)
        }
        //焦外成像
        val bokehPreviewExtender = BokehPreviewExtender.create(previewBuilder)
        if (bokehPreviewExtender.isExtensionAvailable(cameraSelector)) {
            bokehPreviewExtender.enableExtension(cameraSelector)
        }
        //HDR
        val hdrPreviewExtender = HdrPreviewExtender.create(previewBuilder)
        if (hdrPreviewExtender.isExtensionAvailable(cameraSelector)) {
            hdrPreviewExtender.enableExtension(cameraSelector)
        }
        //美颜
        val beautyPreviewExtender = BeautyPreviewExtender.create(previewBuilder)
        if (beautyPreviewExtender.isExtensionAvailable(cameraSelector)) {
            beautyPreviewExtender.enableExtension(cameraSelector)
        }
        //夜间模式
        val nightPreviewExtender = NightPreviewExtender.create(previewBuilder)
        if (nightPreviewExtender.isExtensionAvailable(cameraSelector)) {
            nightPreviewExtender.enableExtension(cameraSelector)
        }
    }

    private fun setImageCapture(
        imageCaptureBuilder: ImageCapture.Builder,
        cameraSelector: CameraSelector
    ) {
        //自动效果，可能是白平衡那些
        val autoImageCaptureExtender = AutoImageCaptureExtender.create(imageCaptureBuilder)
        if (autoImageCaptureExtender.isExtensionAvailable(cameraSelector)) {
            autoImageCaptureExtender.enableExtension(cameraSelector)
        }
        //焦外成像
        val bokehImageCaptureExtender = BokehImageCaptureExtender.create(imageCaptureBuilder)
        if (bokehImageCaptureExtender.isExtensionAvailable(cameraSelector)) {
            bokehImageCaptureExtender.enableExtension(cameraSelector)
        }
        //HDR
        val hdrImageCaptureExtender = HdrImageCaptureExtender.create(imageCaptureBuilder)
        if (hdrImageCaptureExtender.isExtensionAvailable(cameraSelector)) {
            hdrImageCaptureExtender.enableExtension(cameraSelector)
        }
        //美颜
        val beautyImageCaptureExtender = BeautyImageCaptureExtender.create(imageCaptureBuilder)
        if (beautyImageCaptureExtender.isExtensionAvailable(cameraSelector)) {
            beautyImageCaptureExtender.enableExtension(cameraSelector)
        }
        //夜间模式
        val nightImageCaptureExtender = NightImageCaptureExtender.create(imageCaptureBuilder)
        if (nightImageCaptureExtender.isExtensionAvailable(cameraSelector)) {
            nightImageCaptureExtender.enableExtension(cameraSelector)
        }
    }


}